home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
QRZ! Ham Radio 4
/
QRZ Ham Radio Callsign Database - Volume 4.iso
/
files
/
dsp
/
56ktools
/
dspkgctr.z
/
dspkgctr
/
gcc
/
config
/
out-dsp16.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-06-08
|
53KB
|
2,497 lines
/* subroutines for insn-output.c for motorola dsp561XX.
copyright ( c ) 1988 free software foundation, inc.
$Id: out-dsp16.c,v 1.2 91/09/18 15:34:49 jeff Exp $
this file is part of gnu cc.
gnu cc is distributed in the hope that it will be useful,
but without any warranty. no author or distributor
accepts responsibility to anyone for the consequences of using it
or for whether it serves any particular purpose or works at all,
unless he says so in writing. refer to the gnu cc general public
license for full details.
everyone is granted permission to copy, modify and redistribute
gnu cc, but only under the conditions described in the
gnu cc general public license. a copy of this license is
supposed to have been given to you along with gnu cc so you
can know your rights and responsibilities. it should be in a
file named copying. among other things, the copyright notice
and this notice must be preserved on all copies. */
#ifndef file
#include <stdio.h>
#endif
#include <string.h>
#if defined ( _MSDOS )
extern void *malloc( );
#endif
#include <ctype.h>
#include "flags.h"
#include "tree.h"
#if ! defined( _INTELC32_ )
#include "hard-reg-set.h"
#else
#include "hardrset.h"
#endif
char mem_space = 'y';
char memory_model = 'y';
func_attributes current_func_info = FUNC_NO_INFO;
static char local_call_used_regs[] = CALL_USED_REGISTERS;
enum reg_class regno_reg_class ( );
int FirstSave;
void
PushRegs ( file )
FILE* file;
{
int reg_index;
FirstSave = -1;
for ( reg_index = 0; reg_index < FIRST_PSEUDO_REGISTER; ++ reg_index )
{
if ( regs_ever_live[ reg_index ] &&
! local_call_used_regs[ reg_index ] )
{
if ( 0 > FirstSave )
{
FirstSave = reg_index;
}
if ( DST_REGS == REGNO_REG_CLASS ( reg_index ))
{
if ( 'l' == memory_model )
{
fprintf ( file, "\
move %c10,l:(r3)+\n", *reg_names[ reg_index ] );
}
else
{
fprintf ( file, "\
move %s0,%c:(r3)+\n\
move %s1,%c:(r3)+\n", reg_names[ reg_index ], mem_space,
reg_names[ reg_index ], mem_space );
}
}
else if ( SRC_REGS == REGNO_REG_CLASS ( reg_index ) ||
MPY_REGS == REGNO_REG_CLASS ( reg_index ))
{
if ( 'l' == memory_model )
{
/* try to save x or y as a pair. */
if ( reg_index & 1 )
{
/* x1 or y1 */
if ( ! ( regs_ever_live[ reg_index - 1 ] &&
! local_call_used_regs[ reg_index - 1 ] ))
{
/* was the 0 portion saved ? if so, then we
don't need to do anything, else save the 1 ! */
fprintf ( file, "\
move %s,%c:(r3)+\n", reg_names[ reg_index ], mem_space );
}
}
else
{
/* x0 or y0 */
if ( regs_ever_live[ reg_index + 1 ] &&
! local_call_used_regs[ reg_index + 1 ] )
{
/* are we also saving the 1 portion ? if so,
save the 1 as well as the 0 with an l: move.
otherwise, just save the 0. */
fprintf ( file, "\
move %c,l:(r3)+\n", *reg_names[ reg_index ] );
}
else
{
fprintf ( file, "\
move %s,%c:(r3)+\n", reg_names[ reg_index ], mem_space );
}
}
}
else
{
fprintf ( file, "\
move %s,%c:(r3)+\n", reg_names[ reg_index ], mem_space );
}
}
else
{
fprintf ( file, "\
move %s,%c:(r3)+\n", reg_names[ reg_index ], mem_space );
}
}
}
}
void
PopRegs ( file )
FILE* file;
{
int reg_index = FIRST_PSEUDO_REGISTER;
int first_save = 0;
#define SAVE_CHECK \
{\
if ( ! first_save )\
{\
first_save = 1;\
fprintf ( file, "\tmove (r3)-\n" );\
}\
}
while ( -- reg_index >= 0 )
{
if ( regs_ever_live[ reg_index ] &&
! local_call_used_regs[ reg_index ] )
{
SAVE_CHECK;
if ( DST_REGS == REGNO_REG_CLASS ( reg_index ))
{
if ( reg_index == FirstSave )
{
if ( 'l' == memory_model )
{
fprintf ( file, "\
move l:(r3),%c\n", *reg_names[ reg_index ] );
}
else
{
fprintf ( file, "\
move %c:(r3)-,%s\n\
move %c:(r3),%s0\n", mem_space, reg_names[ reg_index ],
mem_space, reg_names[ reg_index ] );
}
}
else
{
if ( 'l' == memory_model )
{
fprintf ( file, "\
move l:(r3)-,%c\n", *reg_names[ reg_index ] );
}
else
{
fprintf ( file, "\
move %c:(r3)-,%s\n\
move %c:(r3)-,%s0\n", mem_space, reg_names[ reg_index ],
mem_space, reg_names[ reg_index ] );
}
}
}
else if ( SRC_REGS == REGNO_REG_CLASS ( reg_index ) ||
MPY_REGS == REGNO_REG_CLASS ( reg_index ))
{
if ( 'l' == memory_model )
{
if ( reg_index & 1 )
{
/* x1 or y1 */
if ( ! ( regs_ever_live[ reg_index -1 ] &&
! local_call_used_regs[ reg_index - 1 ] ))
{
/* if the 0 portion wasn't saved we need to
restore the 1, otherwise do nothing. */
if ( reg_index == FirstSave )
{
fprintf ( file, "\
move %c:(r3),%s\n", mem_space, reg_names[ reg_index ] );
}
else
{
fprintf ( file, "\
move %c:(r3)-,%s\n", mem_space, reg_names[ reg_index ] );
}
}
}
else
{
/* x0 or y0 */
if ( regs_ever_live[ reg_index + 1 ] &&
! local_call_used_regs[ reg_index + 1 ] )
{
/* if the 1 portion was also saved, then we
need to to do an l: restore, otherwise a y:. */
if ( reg_index == FirstSave )
{
fprintf ( file, "\
move l:(r3),%c\n", *reg_names[ reg_index ] );
}
else
{
fprintf ( file, "\
move l:(r3)-,%c\n", *reg_names[ reg_index ] );
}
}
else
{
if ( reg_index == FirstSave )
{
fprintf ( file, "\
move %c:(r3),%s\n", mem_space, reg_names[ reg_index ] );
}
else
{
fprintf ( file, "\
move %c:(r3)-,%s\n", mem_space, reg_names[ reg_index ] );
}
}
}
}
else
{
if ( reg_index == FirstSave )
{
fprintf ( file, "\
move %c:(r3),%s\n", mem_space, reg_names[ reg_index ] );
}
else
{
fprintf ( file, "\
move %c:(r3)-,%s\n", mem_space, reg_names[ reg_index ] );
}
}
}
else
{
if ( reg_index == FirstSave )
{
fprintf ( file, "\
move %c:(r3),%s\n", mem_space, reg_names[ reg_index ] );
}
else
{
fprintf ( file, "\
move %c:(r3)-,%s\n", mem_space, reg_names[ reg_index ] );
}
}
}
}
}
int
go_if_legitimate_address ( mode, x, strict )
int mode;
rtx x;
int strict;
{
/* constant pointer */
if ( CONSTANT_ADDRESS_P ( x ) )
{
return 1;
}
/* note that REG_OK_STRICT may NOT be defined here! */
/* register pointer */
if ( REG_P ( x ) &&
(( strict ) ?
( REGNO_OK_FOR_INDEX_P ( REGNO ( x ))) :
( REG_OK_FOR_INDEX_P ( x ))))
{
return 1;
}
/* register arithmetic */
switch ( GET_CODE ( x ) )
{
case SUBREG:
return go_if_legitimate_address ( mode, XEXP ( x, 0 ), strict );
case POST_DEC:
case POST_INC:
case PRE_INC:
case PRE_DEC:
if ( REG_P ( XEXP ( x, 0 )) &&
(( strict ) ?
( REGNO_OK_FOR_INDEX_P ( REGNO ( XEXP ( x, 0 )))) :
( REG_OK_FOR_INDEX_P ( XEXP ( x, 0 )))))
{
return 1;
}
break;
case PLUS:
if ( REG_P ( XEXP ( x, 0 )) &&
( Pmode == GET_MODE ( XEXP ( x, 0 ))) &&
( CONST_INT == GET_CODE ( XEXP ( x, 1 ))) &&
(( strict ) ?
( REGNO_OK_FOR_INDEX_P ( REGNO ( XEXP ( x, 0 )))) :
( REG_OK_FOR_INDEX_P ( XEXP ( x, 0 )))))
{
return 1;
}
if ( REG_P ( XEXP ( x, 1 )) &&
( Pmode == GET_MODE ( XEXP ( x, 1 ))) &&
( CONST_INT == GET_CODE ( XEXP ( x, 0 ))) &&
(( strict ) ?
( REGNO_OK_FOR_INDEX_P ( REGNO ( XEXP ( x, 1 )))) :
( REG_OK_FOR_INDEX_P ( XEXP ( x, 1 )))))
{
return 1;
}
}
return 0;
}
void
print_operand_address ( file, addr )
FILE* file;
rtx addr;
{
register rtx reg0;
register rtx reg1;
switch ( GET_CODE ( addr ) )
{
case REG:
fprintf ( file, "(%s)", reg_names[ REGNO ( addr )] );
break;
case POST_INC:
fprintf ( file, "(%s)+", reg_names[ REGNO ( XEXP ( addr, 0 ) )] );
break;
case POST_DEC:
fprintf ( file, "(%s)-", reg_names[ REGNO ( XEXP ( addr, 0 ) )] );
break;
case PLUS:
abort ( );
default:
output_addr_const ( file, addr );
}
}
void
notice_update_cc ( exp, insn )
rtx exp;
rtx insn;
{
if ( PARALLEL == GET_CODE ( exp ))
{
rtx call_insn = XVECEXP ( exp, 0, 0 );
if ( GET_CODE ( call_insn ) == SET &&
GET_CODE ( XEXP ( call_insn, 1 )) == CALL )
{
cc_status.flags = 0;
cc_status.value1 = cc0_rtx;
cc_status.value2 = gen_rtx ( REG, SImode, DSP16_A_REGNUM );
cc_status.mdep = CC_SIGNED;
}
else
{
CC_STATUS_INIT;
}
}
else if ( SET == GET_CODE ( exp ))
{
switch ( GET_CODE ( SET_DEST ( exp )))
{
case CC0:
cc_status.flags = 0;
cc_status.value1 = SET_DEST ( exp );
cc_status.value2 = SET_SRC ( exp );
break;
case REG:
CC_STATUS_INIT;
}
}
else
{
CC_STATUS_INIT;
}
}
rtx
next_cc_relevancy ( insn )
rtx insn;
{
rtx peek = NEXT_INSN ( insn );
for ( ; NULL != peek; peek = NEXT_INSN ( peek ))
{
switch ( GET_CODE( peek ))
{
case JUMP_INSN:
case CALL_INSN:
case CODE_LABEL:
case BARRIER:
return peek;
case INSN:
if (( PARALLEL == GET_CODE ( PATTERN ( peek ))) &&
( SET == GET_CODE ( XVECEXP ( PATTERN ( peek ), 0, 0 ))) &&
( 0 == strcmp ( GET_RTX_FORMAT ( GET_CODE ( XEXP ( XVECEXP ( PATTERN ( peek ), 0, 0 ), 1 ))), "ee" )) &&
( cc0_rtx == XEXP ( XEXP ( XVECEXP ( PATTERN ( peek ), 0, 0 ), 1 ), 0 )))
{
return peek;
}
}
}
return insn;
}
enum mdep_cc_info
next_cc_use ( insn )
rtx insn;
{
enum rtx_code jump_code;
rtx peek = NEXT_INSN ( insn );
for ( ; NULL != peek; peek = NEXT_INSN ( peek ))
{
if ( JUMP_INSN == GET_CODE ( peek ))
{
break;
}
if ( CALL_INSN == GET_CODE ( peek ) ||
CODE_LABEL == GET_CODE ( peek ) ||
BARRIER == GET_CODE ( peek ) )
{
return CC_UNKNOWN;
}
if ( INSN == GET_CODE ( peek ) &&
PARALLEL == GET_CODE ( PATTERN ( peek )) &&
SET == GET_CODE ( XVECEXP ( PATTERN ( peek ), 0, 0 )) &&
0 == strcmp ( GET_RTX_FORMAT ( GET_CODE ( XEXP ( XVECEXP ( PATTERN ( peek ), 0, 0 ), 1 ))), "ee" ) &&
( cc0_rtx == XEXP ( XEXP ( XVECEXP ( PATTERN ( peek ), 0, 0 ), 1 ), 0 ) ||
cc0_rtx == XEXP ( XEXP ( XVECEXP ( PATTERN ( peek ), 0, 0 ), 1 ), 1 )))
{
jump_code = GET_CODE ( XEXP ( XVECEXP ( PATTERN ( peek ), 0, 0 ), 1 ));
if ( GEU == jump_code || GTU == jump_code || LEU == jump_code
|| LTU == jump_code )
{
return CC_UNSIGNED;
}
else
{
return CC_SIGNED;
}
}
}
if (( NULL == peek ) ||
( JUMP_INSN != GET_CODE ( peek )) ||
( SET != GET_CODE ( PATTERN ( peek ))) ||
( IF_THEN_ELSE != GET_CODE ( XEXP ( PATTERN ( peek ), 1 ))))
{
return CC_UNKNOWN;
}
jump_code = GET_CODE ( XEXP ( XEXP ( PATTERN ( peek ), 1 ), 0 ));
if ( GEU == jump_code || GTU == jump_code || LEU == jump_code
|| LTU == jump_code || EQU == jump_code || NEU == jump_code )
{
return CC_UNSIGNED;
}
else
{
return CC_SIGNED;
}
}
/* hard_regno_mode_ok -
* this global function implements the tm-m56k.h file macro of the same name.
* a 1 is returned if regno can be used to hold a value of type mode.
*/
int
hard_regno_mode_ok ( regno, mode )
int regno;
int mode;
{
switch ( mode )
{
case VOIDmode:
return 1;
case SFmode:
case DFmode:
case DImode:
/* for doubles, floats, and longs, we need 48-bit registers. */
if ( DSP16_X0_REGNUM == regno || DSP16_Y0_REGNUM == regno ||
DSP16_A_REGNUM == regno || DSP16_B_REGNUM == regno )
{
return 1;
}
else
{
return 0;
}
break;
case PSImode:
/* for pointers we can use any register. */
return 1;
default:
/* for all other cases, we assume that a 16-bit reg is needed. */
if ( regno < 6 )
{
return 1;
}
else
{
return 0;
}
break;
}
}
/* modes_tieable_p -
* this global function implements the tm-m56k.h file macro of the same name.
* a 1 is returned if both modes can always use the same pseudo register.
*/
int
modes_tieable_p ( mode1, mode2 )
int mode1;
int mode2;
{
if ( mode1 == mode2 )
{
return 1;
}
switch ( mode1 )
{
case SFmode:
case DFmode:
case DImode:
if ( SFmode == mode2 || DFmode == mode2 || DImode == mode2 )
{
return 1;
}
else
{
return 0;
}
break;
}
return 0;
}
/* regno_reg_class -
* this global function implements the tm-m56k.h file macro of the same name.
* the class number of the smallest class containing reg number regno is
* returned.
*/
enum reg_class
regno_reg_class ( regno )
int regno;
{
switch ( regno )
{
case DSP16_X0_REGNUM:
case DSP16_Y0_REGNUM:
return MPY_REGS;
case DSP16_X1_REGNUM:
case DSP16_Y1_REGNUM:
return SRC_REGS;
case DSP16_A_REGNUM:
case DSP16_B_REGNUM:
return DST_REGS;
default:
if ( regno < 10 )
{
return ADDR_REGS;
}
return ALL_REGS;
}
}
/* reg_class_from_letter -
* this global function implements the tm-m56k.h file macro of the same name.
* the class number of the given letter is returned.
*/
enum reg_class
reg_class_from_letter ( c )
char c;
{
switch ( c )
{
case 'S':
return SRC_REGS;
case 'D':
return DST_REGS;
case 'A':
return ADDR_REGS;
case 'R':
return MPY_REGS;
default:
return NO_REGS;
}
}
/* reg_class_from_letter -
* this global function implements the tm-m56k.h file macro of the same name.
* the max number of consecutive registers needed per mode is returned.
*/
int
class_max_nregs ( class, mode )
int class;
int mode;
{
if (( SFmode == mode || DFmode == mode || DImode == mode ) &&
( SRC_REGS == class ))
{
return 2;
}
else
{
return 1;
}
}
/* ---------------------------------------------------------------- *\
name dgetmant
synopsis dgetmant(dfptval, wordnum)
double dfptval;
int wordnum;
description
Inputs:
dfptval = double precision value from which mantissa is extracted
wordnum: 0 = upper 20 bits (leading 1 suppressed)
1 = lower 32 bits
return value
\* ---------------------------------------------------------------- */
#if 0
long dgetmant(dfptval, wordnum)
double dfptval;
int wordnum;
{
long *ivalptr;
ivalptr = (long *) &dfptval;
#if defined( _MSDOS ) || defined( MIPSEL )
if (wordnum == 0)
return( ((*(ivalptr+1))) & 0x000fffffL);
else /* lower word */
return( *(ivalptr) );
#else
if (wordnum == 0)
return( ((*ivalptr)) & 0x000fffff);
else /* lower word */
return( *(ivalptr+1) );
#endif
}
long dgetexp(dfptval)
double dfptval;
{
long *ivalptr;
ivalptr = (long *) &dfptval;
#if defined( _MSDOS ) || defined( MIPSEL )
ivalptr++;
#endif
return( ((*ivalptr)>>20) & 0x07ff ); /* masks sign bit too */
}
union real_extract adjusted_dval;
void
dtok ( file, dval )
FILE* file;
union real_extract dval;
{
unsigned long L_word, H_word, tmp, tmp2, dsgn;
long increase_exponent;
if ( dval.d == 0 )
{
H_word = L_word = 0;
}
else
{
L_word = dgetexp(dval.d); /* ieee exponent */
H_word = dgetmant(dval.d,0); /* grab upper 20 bits of double */
tmp2=dgetmant(dval.d,1); /* lower 32 bits of ieee mantissa */
/* ieee denormalized number */
if ( L_word == 0 )
{
L_word++; /* try it*/
/* normalize it */
while ( ! ( H_word & 0x100000 ) )
{
L_word -- ; /* exponent decreases */
H_word <<= 1 ; /* shift entire 52 bit ieee mantissa left */
if ( tmp2 & 0x80000000l )
{
H_word |= 1 ;
}
tmp2 <<= 1 ;
}
}
/* normalized ieee number with implied leading 1 */
else
{
H_word |= 0x00100000; /* add leading 1 */
}
H_word <<= 10;
tmp = ((tmp2 & 0xc0000000) >> 1); /* grab lower 2 bits */
tmp >>= 21; /* ------------------- */
H_word |= tmp; /* combine upper and lower */
increase_exponent=0;
/* round up for 1/2 lsb of kp mantissa */
if ( tmp2 & 0x20000000l )
{
if ( H_word >= 0x7fffff00 )
{
increase_exponent = 1;
H_word += 0x100;
H_word >>= 1;
}
else
{
H_word += 0x100;
}
}
#if defined( _MSDOS ) || defined( MIPSEL )
dsgn = ( * (long *) &(dval.i[1]) ) & 0x80000000l;
#else /* real computers */
dsgn = ( * (long *) &(dval.i[0]) ) & 0x80000000l;
#endif
/* check for negative value in ieee format */
if ( dsgn )
{
H_word = -H_word;
}
H_word >>= 8;
L_word -= 1023; /* IEEE double precision bias */
L_word += 8191; /* kevFP little precision bias */
L_word ++; /* lameFP s.xxx..xx */
L_word += increase_exponent; /* in case rounding modified exponent */
/* negative weird case ( -0.5 == 800000 not c00000 ) */
if ( (H_word & 0x800000) && (H_word & 0x400000) )
{
H_word <<= 1;
L_word--;
}
}
if ( NULL != file )
{
if ( 'l' == memory_model )
{
fprintf ( file, "\tdc\t$%06x%06x\n", H_word & 0xffffff,
L_word & 0xffffff );
}
else
{
fprintf ( file, "\tdc\t$%06x\n\tdc\t$%06x\n", L_word & 0xffffff,
H_word & 0xffffff );
}
}
adjusted_dval.i[1] = ( 0x00ffffff & H_word );
adjusted_dval.i[0] = ( 0x00ffffff & L_word );
}
#endif
int
local_first_parm_offset ( fundecl )
tree fundecl;
{
tree arg_list;
#if 0
if (( NULL == fundecl ) ||
( NULL == ( arg_list = DECL_ARGUMENTS ( fundecl ))))
{
return -4;
}
return - int_size_in_bytes ( DECL_ARG_TYPE ( arg_list )) + -3;
#else
return -2;
#endif
}
void
print_operand ( file, x, code )
FILE* file;
rtx x;
char code;
{
rtx ensure_pointer_result_size ( );
rtx ensure_integer_result_size ( );
if ( 'p' == code )
{
x = ensure_pointer_result_size ( copy_rtx ( x ));
output_addr_const ( file, x );
return;
}
else if ( 'q' == code )
{
x = ensure_integer_result_size ( copy_rtx ( x ));
output_addr_const ( file, x );
return;
}
switch ( GET_CODE ( x ) )
{
case REG:
switch ( code )
{
case 'd':
fprintf ( file, "%s", reg_names[ REGNO ( x ) ] );
break;
case 'e':
if ( DST_REGS == REGNO_REG_CLASS ( REGNO ( x )))
{
if ( MEM_IN_STRUCT_P ( x ))
{
/* see comment in final.c */
fprintf ( file, "%s0", reg_names[ REGNO ( x ) ] );
}
else
{
fprintf ( file, "%s1", reg_names[ REGNO ( x ) ] );
}
}
else
{
fprintf ( file, "%s", reg_names[ REGNO ( x ) ] );
}
break;
case 'g':
fprintf ( file, "%s", reg_names[ REGNO ( x ) ^ 1 ] );
break;
case 'h':
fprintf ( file, "%s0", reg_names[ REGNO ( x ) ] );
break;
case 'i':
fprintf ( file, "%c", *( reg_names[ REGNO ( x ) ] ));
break;
case 'j':
fprintf ( file, "n%c", * ( reg_names[ REGNO ( x ) ] + 1 ));
break;
case 'k':
fprintf ( file, "%s2", reg_names[ REGNO ( x ) ] );
break;
case 'm':
fprintf ( file, "%c", (reg_names[ REGNO ( x ) ])[0] );
break;
case 'o':
fprintf ( file, "%c10", (reg_names[ REGNO ( x ) ])[0] );
break;
default:
if ( MEM_IN_STRUCT_P ( x ))
{
/* see comment in final.c */
fprintf ( file, "%s0", reg_names[ REGNO ( x ) ] );
}
else
{
fprintf ( file, "%s", reg_names[ REGNO ( x ) ] );
}
break;
}
break;
case MEM:
switch ( code )
{
case 'f':
/* print out a 'l' instead of an x or y when we need to */
if (( 'l' == memory_model ) &&
(( DImode == GET_MODE ( x )) ||
( SFmode == GET_MODE ( x )) ||
( DFmode == GET_MODE ( x ))))
{
fprintf ( file, "l:" );
}
else
{
fprintf ( file, "%c:", mem_space );
}
output_address ( ensure_pointer_result_size
( copy_rtx ( XEXP ( x, 0 ))));
break;
default:
output_address ( ensure_pointer_result_size
( copy_rtx ( XEXP ( x, 0 ))));
}
return;
case CONST_INT:
if ( 0 == ( INTVAL ( x ) >> 8 ))
{
fprintf ( file, "#>$%02x", INTVAL ( x ) );
}
else
{
fprintf ( file, "#>$%04x", INTVAL ( x ) );
}
return;
default:
#if 0
fprintf ( file, "#" );
if ( CONSTANT_ADDRESS_P ( x ))
{
output_addr_const ( file, x );
}
else
{
output_operand ( x, 'c' );
}
#endif
abort ( );
}
}
void
simplify_cse_victims ( first )
rtx first;
{
rtx point, elem;
while ( first )
{
/* is it a 3 element PARALLEL ? */
if (( INSN == GET_CODE ( first )) &&
( point = PATTERN ( first ), PARALLEL == GET_CODE ( point )) &&
( 3 == XVECLEN ( point, 0 )) &&
/* is the 1st element a ( SET ( REG ) ( REG / CONST_INT )) ? */
( elem = XVECEXP ( point, 0, 0 ), SET == GET_CODE ( elem )) &&
( REG == GET_CODE ( SET_DEST ( elem ))) &&
(( REG == GET_CODE ( SET_SRC ( elem ))) ||
( CONST == GET_CODE ( SET_SRC ( elem ))) ||
( CONST_INT == GET_CODE ( SET_SRC ( elem )))) &&
/* is the 2nd element a ( CLOBBER ( REG )) ? */
( elem = XVECEXP ( point, 0, 1 ), CLOBBER == GET_CODE ( elem )) &&
( REG == GET_CODE ( XEXP ( elem, 0 ))) &&
/* is the 3rd element a ( CLOBBER ( REG )) ? */
( elem = XVECEXP ( point, 0, 2 ), CLOBBER == GET_CODE ( elem )) &&
( REG == GET_CODE ( XEXP ( elem, 0 ))))
{
/* we've got a blown-out div template ! substitute with a simple
( SET ( REG ) ( REG / CONST_INT )) (note: really the 1st
element of the parallel). */
PATTERN ( first ) = XVECEXP ( point, 0, 0 );
}
first = NEXT_INSN ( first );
}
}
static int
mpy_insn_p ( insn )
rtx insn;
{
return (( INSN == GET_CODE ( insn )) &&
( SET == GET_CODE ( PATTERN ( insn ))) &&
( REG == GET_CODE ( SET_DEST ( PATTERN ( insn )))) &&
( MULT == GET_CODE ( SET_SRC ( PATTERN ( insn )))));
}
static int
mac_insn_p ( insn )
rtx insn;
{
/* mac +/- shape detector. */
return (( INSN == GET_CODE ( insn )) &&
( SET == GET_CODE ( PATTERN ( insn ))) &&
( REG == GET_CODE ( SET_DEST ( PATTERN ( insn )))) &&
(( PLUS == GET_CODE ( SET_SRC ( PATTERN ( insn )))) ||
( MINUS == GET_CODE ( SET_SRC ( PATTERN ( insn ))))) &&
(( MULT == GET_CODE ( XEXP ( SET_SRC ( PATTERN ( insn )), 0 ))) ||
( MULT == GET_CODE ( XEXP ( SET_SRC ( PATTERN ( insn )), 1 )))));
}
static rtx
mac_addative_input ( mac )
rtx mac;
{
return ( MULT == GET_CODE ( XEXP ( SET_SRC ( PATTERN ( mac )), 0 ))) ?
XEXP ( SET_SRC ( PATTERN ( mac )), 1 ) :
XEXP ( SET_SRC ( PATTERN ( mac )), 0 );
}
void
reduce_norm_freq ( first )
rtx first;
{
/* point to the last insn.
search up the list for each mac insn:
detemine the addative_input.
foreach insn in LOG_LINKS( point ):
if insn SETs the addative_input, and insn is a mac or mpy, and
there are no reload generated references to the operand
between these two instructions, then:
mark the pointed to mac as not needing input normalization
mark the mpy/mac insn as not needing output normalization.
the templates for mpy/mac will check for these flags. */
rtx last = first, point;
/* find the last insn, search up from it */
while ( NULL != NEXT_INSN ( last ))
{
last = NEXT_INSN ( last );
}
while ( last != first )
{
if ( mac_insn_p ( last ))
{
rtx add_in = mac_addative_input ( last );
rtx insn_chain = LOG_LINKS ( last );
while ( NULL != insn_chain )
{
rtx this_insn = XEXP ( insn_chain, 0 );
if ((( mac_insn_p ( this_insn )) ||
( mpy_insn_p ( this_insn ))) &&
( add_in == SET_DEST ( PATTERN ( this_insn ))) &&
( ! reg_used_between_p ( add_in, this_insn, last )))
{
/* kludge up: re-use existing flags, in_struct and used,
to inhibit the emission of normalization code at the
front and back end of mac (and mpy) instructions. */
/* turn off last's pre-norm. */
MEM_IN_STRUCT_P ( last ) = 1;
/* turn off this_insn's post-norm. */
RTX_UNCHANGING_P ( this_insn ) = 1;
}
insn_chain = XEXP ( insn_chain, 1 );
}
}
last = PREV_INSN ( last );
}
}
/* this extraneous function is needed because the MetaWare C compiler
can't handle the comma operator with pointer values. */
rtx
local_function_incoming_arg ( cum, mode, type, named )
CUMULATIVE_ARGS cum;
enum machine_mode mode;
tree type;
int named;
{
current_func_info |= FUNC_HAS_STACK_PARMS;
return FUNCTION_ARG (cum, mode, type, named);
}
#define N_REG_COUNT 4
#define FIRST_N_REG 6
static rtx current_n_reg_value[ N_REG_COUNT ];
void
clear_n_reg_values ( )
{
int i = N_REG_COUNT;
while ( i -- )
{
current_n_reg_value[i] = NULL;
}
}
int
load_n_reg_p ( reg, new_value )
rtx reg, new_value;
{
if ( current_n_reg_value[ REGNO ( reg ) - FIRST_N_REG ] &&
rtx_equal_p ( current_n_reg_value[ REGNO ( reg ) - FIRST_N_REG ],
new_value ) &&
CONSTANT_P ( new_value ))
{
return 0;
}
else
{
current_n_reg_value[ REGNO ( reg ) - FIRST_N_REG ] = new_value;
return 1;
}
}
/* sort the compares into the signed and unsigned varieties. */
void
sort_compares ( insns )
rtx insns;
{
while ( insns )
{
if (( INSN == GET_CODE ( insns )) &&
( SET == GET_CODE ( PATTERN ( insns ))) &&
( cc0_rtx == SET_DEST ( PATTERN ( insns ))) &&
( CC_UNSIGNED == next_cc_use ( insns )))
{
UNSIGNED_COMPARE_P ( insns ) = 1;
}
insns = NEXT_INSN ( insns );
}
}
char*
move_singleword ( operands )
rtx *operands;
{
extern char mem_space;
if (( rtx_equal_p ( operands[0], operands[1] )) &&
(( REG != GET_CODE ( operands[0] )) ||
( ! MEM_IN_STRUCT_P ( operands[0] ))) &&
(( REG != GET_CODE ( operands[1] )) ||
( ! MEM_IN_STRUCT_P ( operands[1] ))))
{
/* if we're doing a nop move, return a null string. note that
an insn could look like a nop move isasmuchas rtx_equal_p returns
true; however the MEM_IN_STRUCT_P kludge used by alter_subreg ( )
(final.c) may indicate a move from the LSW of a long to an int
in the same accumulator. */
return "";
}
switch ( which_alternative )
{
case 0:
if ( MEM_IN_STRUCT_P ( operands[0] ) ||
MEM_IN_STRUCT_P ( operands[1] ))
{
return "move %1,%0";
}
else
{
return "tfr %1,%0";
}
case 1:
return "move %e1,%0";
case 2:
if ( PLUS == GET_CODE ( XEXP ( operands[0], 0 )))
{
if ( REG == GET_CODE ( XEXP ( XEXP ( operands[0], 0 ), 0 )))
{
operands[2] = XEXP ( XEXP ( operands[0], 0 ), 0 );
operands[3] = XEXP ( XEXP ( operands[0], 0 ), 1 );
}
else
{
operands[2] = XEXP ( XEXP ( operands[0], 0 ), 1 );
operands[3] = XEXP ( XEXP ( operands[0], 0 ), 0 );
}
if ( CONST_INT != GET_CODE ( operands[3] ))
{
if ( load_n_reg_p ( operands[2], operands[3] ))
{
RETURN_DSP ( "move #%p3,%j2\n\tmove %e1,@:(%2+%j2)" );
}
else
{
RETURN_DSP ( "move %e1,@:(%2+%j2)" );
}
}
switch ( INTVAL ( operands[3] ))
{
case 0:
RETURN_DSP ( "move %e1,@:(%2)" );
case 1:
if ( REGNO ( operands[2] ) != REGNO ( operands[1] ))
{
RETURN_DSP ( "move (%2)+\n\tmove %e1,@:(%2)-" );
}
case -1:
if ( REGNO ( operands[2] ) != REGNO ( operands[1] ))
{
RETURN_DSP ( "move (%2)-\n\tmove %e1,@:(%2)+" );
}
default:
if ( load_n_reg_p ( operands[2], operands[3] ))
{
RETURN_DSP ( "move #%p3,%j2\n\tmove %e1,@:(%2+%j2)" );
}
else
{
RETURN_DSP ( "move %e1,@:(%2+%j2)" );
}
}
}
else
{
return "move %e1,%f0";
}
case 3:
if ( PLUS == GET_CODE ( XEXP ( operands[1], 0 )))
{
if ( REG == GET_CODE ( XEXP ( XEXP ( operands[1], 0 ), 0 )))
{
operands[2] = XEXP ( XEXP ( operands[1], 0 ), 0 );
operands[3] = XEXP ( XEXP ( operands[1], 0 ), 1 );
}
else
{
operands[2] = XEXP ( XEXP ( operands[1], 0 ), 1 );
operands[3] = XEXP ( XEXP ( operands[1], 0 ), 0 );
}
if ( CONST_INT != GET_CODE ( operands[3] ))
{
if ( load_n_reg_p ( operands[2], operands[3] ))
{
RETURN_DSP ( "move #%p3,%j2\n\tmove @:(%2+%j2),%0" );
}
else
{
RETURN_DSP ( "move @:(%2+%j2),%0" );
}
}
switch ( INTVAL ( operands[3] ))
{
case 0:
RETURN_DSP ( "move @:(%2),%0" );
case 1:
if ( REGNO ( operands[0] ) != REGNO ( operands[2] ))
{
RETURN_DSP ( "move (%2)+\n\tmove @:(%2)-,%0" );
}
case -1:
if ( REGNO ( operands[0] ) != REGNO ( operands[2] ))
{
RETURN_DSP ( "move (%2)-\n\tmove @:(%2)+,%0" );
}
default:
if ( load_n_reg_p ( operands[2], operands[3] ))
{
RETURN_DSP ( "move #%p3,%j2\n\tmove @:(%2+%j2),%0" );
}
else
{
RETURN_DSP ( "move @:(%2+%j2),%0" );
}
}
}
else
{
return "move %f1,%0";
}
case 4:
if ( 0 == INTVAL ( operands[1] ))
{
if ( DST_REGS == REGNO_REG_CLASS ( REGNO ( operands[0] )))
{
return "clr %0";
}
else
{
return "move #%c1,%0";
}
}
else
{
return "move #>%q1,%0";
}
}
}
char*
move_doubleword ( is_float_p, operands )
int is_float_p;
rtx *operands;
{
extern char mem_space;
extern union real_extract adjusted_dval;
if ( rtx_equal_p ( operands[0], operands[1] ))
{
return "";
}
switch ( which_alternative )
{
case 0:
if ( IS_SRC_OR_MPY_P ( REGNO ( operands[1] )))
{
if ( MEM_IN_STRUCT_P ( operands[0] ) ||
MEM_IN_STRUCT_P ( operands[1] ))
{
return "move %g1,%0\n\tmove %1,%h0";
}
else
{
return "tfr %g1,%0\n\tmove %1,%h0";
}
}
else
{
if ( MEM_IN_STRUCT_P ( operands[0] ) ||
MEM_IN_STRUCT_P ( operands[1] ))
{
return "move %1,%0";
}
else
{
return "tfr %1,%0";
}
}
case 1:
if ( IS_SRC_OR_MPY_P ( REGNO ( operands[1] )))
{
return "move %g1,%g0\n\tmove %1,%0";
}
else
{
return "move %e1,%g0\n\tmove %h1,%0";
}
case 2:
if ( 'l' == memory_model )
{
if ( PLUS == GET_CODE ( XEXP ( operands[0], 0 )))
{
if ( REG == GET_CODE ( XEXP ( XEXP ( operands[0], 0 ), 0 )))
{
operands[2] = XEXP ( XEXP ( operands[0], 0 ), 0 );
operands[3] = XEXP ( XEXP ( operands[0], 0 ), 1 );
}
else
{
operands[2] = XEXP ( XEXP ( operands[0], 0 ), 1 );
operands[3] = XEXP ( XEXP ( operands[0], 0 ), 0 );
}
if ( CONST_INT != GET_CODE ( operands[3] ))
{
if ( IS_SRC_OR_MPY_P ( REGNO ( operands[1] )))
{
if ( load_n_reg_p ( operands[2], operands[3] ))
{
return "move #%p3,%j2\n\tmove %m1,l:(%2+%j2)";
}
else
{
return "move %m1,l:(%2+%j2)";
}
}
else
{
if ( load_n_reg_p ( operands[2], operands[3] ))
{
return "move #%p3,%j2\n\tmove %o1,l:(%2+%j2)";
}
else
{
return "move %o1,l:(%2+%j2)";
}
}
}
switch ( INTVAL ( operands[3] ))
{
case 0:
if ( IS_SRC_OR_MPY_P ( REGNO ( operands[1] )))
{
return "move %m1,l:(%2)";
}
else
{
return "move %o1,l:(%2)";
}
case 1:
if ( IS_SRC_OR_MPY_P ( REGNO ( operands[1] )))
{
return "move (%2)+\n\tmove %m1,l:(%2)-";
}
else
{
return "move (%2)+\n\tmove %o1,l:(%2)-";
}
case -1:
if ( IS_SRC_OR_MPY_P ( REGNO ( operands[1] )))
{
return "move (%2)-\n\tmove %m1,l:(%2)+";
}
else
{
return "move (%2)-\n\tmove %o1,l:(%2)+";
}
default:
if ( IS_SRC_OR_MPY_P ( REGNO ( operands[1] )))
{
if ( load_n_reg_p ( operands[2], operands[3] ))
{
return "move #%p3,%j2\n\tmove %m1,l:(%2+%j2)";
}
else
{
return "move %m1,l:(%2+%j2)";
}
}
else
{
if ( load_n_reg_p ( operands[2], operands[3] ))
{
return "move #%p3,%j2\n\tmove %o1,l:(%2+%j2)";
}
else
{
return "move %o1,l:(%2+%j2)";
}
}
}
}
else
{
if ( IS_SRC_OR_MPY_P ( REGNO ( operands[1] )))
{
return "move %m1,%f0";
}
else
{
return "move %o1,%f0";
}
}
}
else /* memory_model is x or y. */
{
if ( PLUS == GET_CODE ( XEXP ( operands[0], 0 )))
{
if ( REG == GET_CODE ( XEXP ( XEXP ( operands[0], 0 ), 0 )))
{
operands[2] = XEXP ( XEXP ( operands[0], 0 ), 0 );
operands[3] = XEXP ( XEXP ( operands[0], 0 ), 1 );
}
else
{
operands[2] = XEXP ( XEXP ( operands[0], 0 ), 1 );
operands[3] = XEXP ( XEXP ( operands[0], 0 ), 0 );
}
if ( CONST_INT != GET_CODE ( operands[3] ))
{
if ( IS_SRC_OR_MPY_P ( REGNO ( operands[1] )))
{
if ( load_n_reg_p ( operands[2], operands[3] ))
{
RETURN_DSP ( "move #%p3,%j2\n\tmove (%2)+\n\tmove (%2)+%j2\n\tmove %g1,@:(%2)-\n\tmove %1,@:(%2)-%j2" );
}
else
{
RETURN_DSP ( "move (%2)+\n\tmove (%2)+%j2\n\tmove %g1,@:(%2)-\n\tmove %1,@:(%2)-%j2" );
}
}
else
{
if ( load_n_reg_p ( operands[2], operands[3] ))
{
RETURN_DSP ( "move #%p3,%j2\n\tmove (%2)+\n\tmove (%2)+%j2\n\tmove %e1,@:(%2)-\n\tmove %h1,@:(%2)-%j2" );
}
else
{
RETURN_DSP ( "move (%2)+\n\tmove (%2)+%j2\n\tmove %e1,@:(%2)-\n\tmove %h1,@:(%2)-%j2" );
}
}
}
switch ( INTVAL ( operands[3] ))
{
case 0:
if ( IS_SRC_OR_MPY_P ( REGNO ( operands[1] )))
{
RETURN_DSP ( "move %1,@:(%2)+\n\tmove %g1,@:(%2)-" );
}
else
{
RETURN_DSP ( "move %h1,@:(%2)+\n\tmove %e1,@:(%2)-" );
}
case 1:
if ( IS_SRC_OR_MPY_P ( REGNO ( operands[1] )))
{
RETURN_DSP ( "move (%2)+\n\tmove %1,@:(%2)+\n\tmove %g1,@:(%2)-\n\tmove (%2)-" );
}
else
{
RETURN_DSP ( "move (%2)+\n\tmove %h1,@:(%2)+\n\tmove %e1,@:(%2)-\n\tmove (%2)-" );
}
case -1:
if ( IS_SRC_OR_MPY_P ( REGNO ( operands[1] )))
{
RETURN_DSP ( "move (%2)-\n\tmove %g1,@:(%2)-\n\tmove %1,@:(%2)+\n\tmove (%2)+" );
}
else
{
RETURN_DSP ( "move (%2)-\n\tmove %e1,@:(%2)-\n\tmove %h1,@:(%2)+\n\tmove (%2)+" );
}
default:
if ( IS_SRC_OR_MPY_P ( REGNO ( operands[1] )))
{
if ( load_n_reg_p ( operands[2], operands[3] ))
{
RETURN_DSP ( "move #%p3,%j2\n\tmove (%2)+\n\tmove (%2)+%j2\n\tmove %g1,@:(%2)-\n\tmove %1,@:(%2)-%j2" );
}
else
{
RETURN_DSP ( "move (%2)+\n\tmove (%2)+%j2\n\tmove %g1,@:(%2)-\n\tmove %1,@:(%2)-%j2" );
}
}
else
{
if ( load_n_reg_p ( operands[2], operands[3] ))
{
RETURN_DSP ( "move #%p3,%j2\n\tmove (%2)+\n\tmove (%2)+%j2\n\tmove %e1,@:(%2)-\n\tmove %h1,@:(%2)-%j2" );
}
else
{
RETURN_DSP ( "move (%2)+\n\tmove (%2)+%j2\n\tmove %e1,@:(%2)-\n\tmove %h1,@:(%2)-%j2" );
}
}
}
}
else if ( POST_INC == GET_CODE ( XEXP ( operands[0], 0 )))
{
operands[2] = XEXP ( XEXP ( operands[0], 0 ), 0 );
if ( IS_SRC_OR_MPY_P ( REGNO ( operands[1] )))
{
RETURN_DSP ( "move %1,@:(%2)+\n\tmove %g1,@:(%2)+" );
}
else
{
RETURN_DSP ( "move %h1,@:(%2)+\n\tmove %e1,@:(%2)+" );
}
}
else if ( POST_DEC == GET_CODE ( XEXP ( operands[0], 0 )))
{
operands[2] = XEXP ( XEXP ( operands[0], 0 ), 0 );
if ( IS_SRC_OR_MPY_P ( REGNO ( operands[1] )))
{
if ( load_n_reg_p ( operands[2],
gen_rtx ( CONST_INT, VOIDmode, 3 )))
{
RETURN_DSP ( "move #3,%j2\n\tmove %1,@:(%2)+\n\tmove %g1,@:(%2)-%j2" );
}
else
{
RETURN_DSP ( "move %1,@:(%2)+\n\tmove %g1,@:(%2)-%j2" );
}
}
else
{
if ( load_n_reg_p ( operands[2],
gen_rtx ( CONST_INT, VOIDmode, 3 )))
{
RETURN_DSP ( "move #3,%j2\n\tmove %h1,@:(%2)+\n\tmove %e1,@:(%2)-%j2" );
}
else
{
RETURN_DSP ( "move %h1,@:(%2)+\n\tmove %e1,@:(%2)-%j2" );
}
}
}
else if ( REG == GET_CODE ( XEXP ( operands[0], 0 )))
{
operands[2] = XEXP ( operands[0], 0 );
if ( IS_SRC_OR_MPY_P ( REGNO ( operands[1] )))
{
RETURN_DSP ( "move %1,@:(%2)+\n\tmove %g1,@:(%2)-" );
}
else
{
RETURN_DSP ( "move %h1,@:(%2)+\n\tmove %e1,@:(%2)-" );
}
}
else
{
if ( IS_SRC_OR_MPY_P ( REGNO ( operands[1] )))
{
return "move %1,%f0\n\tmove %g1,%f0+1";
}
else
{
return "move %h1,%f0\n\tmove %e1,%f0+1";
}
}
}
case 3:
if ( 'l' == memory_model )
{
if ( PLUS == GET_CODE ( XEXP ( operands[1], 0 )))
{
if ( REG == GET_CODE ( XEXP ( XEXP ( operands[1], 0 ), 0 )))
{
operands[2] = XEXP ( XEXP ( operands[1], 0 ), 0 );
operands[3] = XEXP ( XEXP ( operands[1], 0 ), 1 );
}
else
{
operands[2] = XEXP ( XEXP ( operands[1], 0 ), 1 );
operands[3] = XEXP ( XEXP ( operands[1], 0 ), 0 );
}
if ( CONST_INT != GET_CODE ( operands[3] ))
{
if ( IS_SRC_OR_MPY_P ( REGNO ( operands[0] )))
{
if ( load_n_reg_p ( operands[2], operands[3] ))
{
return "move #%p3,%j2\n\tmove l:(%2+%j2),%m0";
}
else
{
return "move l:(%2+%j2),%m0";
}
}
else
{
if ( load_n_reg_p ( operands[2], operands[3] ))
{
return "move #%p3,%j2\n\tmove l:(%2+%j2),%0";
}
else
{
return "move l:(%2+%j2),%0";
}
}
}
switch ( INTVAL ( operands[3] ))
{
case 0:
if ( IS_SRC_OR_MPY_P ( REGNO ( operands[0] )))
{
return "move l:(%2),%m0";
}
else
{
return "move l:(%2),%0";
}
case 1:
if ( IS_SRC_OR_MPY_P ( REGNO ( operands[0] )))
{
return "move (%2)+\n\tmove l:(%2)-,%m0";
}
else
{
return "move (%2)+\n\tmove l:(%2)-,%0";
}
case -1:
if ( IS_SRC_OR_MPY_P ( REGNO ( operands[0] )))
{
return "move (%2)-\n\tmove l:(%2)+,%m0";
}
else
{
return "move (%2)-\n\tmove l:(%2)+,%0";
}
default:
if ( IS_SRC_OR_MPY_P ( REGNO ( operands[0] )))
{
if ( load_n_reg_p ( operands[2], operands[3] ))
{
return "move #%p3,%j2\n\tmove l:(%2+%j2),%m0";
}
else
{
return "move l:(%2+%j2),%m0";
}
}
else
{
if ( load_n_reg_p ( operands[2], operands[3] ))
{
return "move #%p3,%j2\n\tmove l:(%2+%j2),%0";
}
else
{
return "move l:(%2+%j2),%0";
}
}
}
}
else
{
if ( IS_SRC_OR_MPY_P ( REGNO ( operands[0] )))
{
return "move %f1,%m0";
}
else
{
return "move %f1,%0";
}
}
}
else /* memory_model is x or y */
{
if ( PLUS == GET_CODE ( XEXP ( operands[1], 0 )))
{
if ( REG == GET_CODE ( XEXP ( XEXP ( operands[1], 0 ), 0 )))
{
operands[2] = XEXP ( XEXP ( operands[1], 0 ), 0 );
operands[3] = XEXP ( XEXP ( operands[1], 0 ), 1 );
}
else
{
operands[2] = XEXP ( XEXP ( operands[1], 0 ), 1 );
operands[3] = XEXP ( XEXP ( operands[1], 0 ), 0 );
}
if ( CONST_INT != GET_CODE ( operands[3] ))
{
if ( IS_SRC_OR_MPY_P ( REGNO ( operands[0] )))
{
if ( load_n_reg_p ( operands[2], operands[3] ))
{
RETURN_DSP ( "move #%p3,%j2\n\tmove (%2)+\n\tmove (%2)+%j2\n\tmove @:(%2)-,%g0\n\tmove @:(%2)-%j2,%0" );
}
else
{
RETURN_DSP ( "move (%2)+\n\tmove (%2)+%j2\n\tmove @:(%2)-,%g0\n\tmove @:(%2)-%j2,%0" );
}
}
else
{
if ( load_n_reg_p ( operands[2], operands[3] ))
{
RETURN_DSP ( "move #%p3,%j2\n\tmove (%2)+\n\tmove (%2)+%j2\n\tmove @:(%2)-,%0\n\tmove @:(%2)-%j2,%h0" );
}
else
{
RETURN_DSP ( "move (%2)+\n\tmove (%2)+%j2\n\tmove @:(%2)-,%0\n\tmove @:(%2)-%j2,%h0" );
}
}
}
switch ( INTVAL ( operands[3] ))
{
case 0:
if ( IS_SRC_OR_MPY_P ( REGNO ( operands[0] )))
{
RETURN_DSP ( "move (%2)+\n\tmove @:(%2)-,%g0\n\tmove @:(%2),%0" );
}
else
{
RETURN_DSP ( "move (%2)+\n\tmove @:(%2)-,%0\n\tmove @:(%2),%h0" );
}
case 1:
if ( IS_SRC_OR_MPY_P ( REGNO ( operands[0] )))
{
RETURN_DSP ( "move (%2)+\n\tmove (%2)+\n\tmove @:(%2)-,%g0\n\tmove @:(%2)-,%0" );
}
else
{
RETURN_DSP ( "move (%2)+\n\tmove (%2)+\n\tmove @:(%2)-,%0\n\tmove @:(%2)-,%h0" );
}
case -1:
if ( IS_SRC_OR_MPY_P ( REGNO ( operands[0] )))
{
RETURN_DSP ( "move (%2)-\n\tmove @:(%2)-,%g0\n\tmove @:(%2)+,%0\n\tmove (%2)+" );
}
else
{
RETURN_DSP ( "move (%2)-\n\tmove @:(%2)-,%0\n\tmove @:(%2)+,%h0\n\tmove (%2)+" );
}
default:
if ( IS_SRC_OR_MPY_P ( REGNO ( operands[0] )))
{
if ( load_n_reg_p ( operands[2], operands[3] ))
{
RETURN_DSP ( "move #%p3,%j2\n\tmove (%2)+\n\tmove (%2)+%j2\n\tmove @:(%2)-,%g0\n\tmove @:(%2)-%j2,%0" );
}
else
{
RETURN_DSP ( "move (%2)+\n\tmove (%2)+%j2\n\tmove @:(%2)-,%g0\n\tmove @:(%2)-%j2,%0" );
}
}
else
{
if ( load_n_reg_p ( operands[2], operands[3] ))
{
RETURN_DSP ( "move #%p3,%j2\n\tmove (%2)+\n\tmove (%2)+%j2\n\tmove @:(%2)-,%0\n\tmove @:(%2)-%j2,%h0" );
}
else
{
RETURN_DSP ( "move (%2)+\n\tmove (%2)+%j2\n\tmove @:(%2)-,%0\n\tmove @:(%2)-%j2,%h0" );
}
}
}
}
else if ( POST_INC == GET_CODE ( XEXP ( operands[1], 0 )))
{
operands[2] = XEXP ( XEXP ( operands[1], 0 ), 0 );
if ( IS_SRC_OR_MPY_P ( REGNO ( operands[0] )))
{
if ( load_n_reg_p ( operands[2],
gen_rtx ( CONST_INT, VOIDmode, 2 )))
{
RETURN_DSP ( "move #2,%j2\n\tmove (%2)+\n\tmove @:(%2)-,%g0\n\tmove @:(%2)+%j2,%0" );
}
else
{
RETURN_DSP ( "move (%2)+\n\tmove @:(%2)-,%g0\n\tmove @:(%2)+%j2,%0" );
}
}
else
{
if ( load_n_reg_p ( operands[2],
gen_rtx ( CONST_INT, VOIDmode, 2 )))
{
RETURN_DSP ( "move #2,%j2\n\tmove (%2)+\n\tmove @:(%2)-,%0\n\tmove @:(%2)+%j2,%h0" );
}
else
{
RETURN_DSP ( "move (%2)+\n\tmove @:(%2)-,%0\n\tmove @:(%2)+%j2,%h0" );
}
}
}
else if ( POST_DEC == GET_CODE ( XEXP ( operands[1], 0 )))
{
operands[2] = XEXP ( XEXP ( operands[1], 0 ), 0 );
if ( IS_SRC_OR_MPY_P ( REGNO ( operands[0] )))
{
if ( load_n_reg_p ( operands[2],
gen_rtx ( CONST_INT, VOIDmode, 2 )))
{
RETURN_DSP ( "move #2,%j2\n\tmove (%2)+\n\tmove @:(%2)-,%g0\n\tmove @:(%2)-%j2,%0" );
}
else
{
RETURN_DSP ( "move (%2)+\n\tmove @:(%2)-,%g0\n\tmove @:(%2)-%j2,%0" );
}
}
else
{
if ( load_n_reg_p ( operands[2],
gen_rtx ( CONST_INT, VOIDmode, 2 )))
{
RETURN_DSP ( "move #2,%j2\n\tmove (%2)+\n\tmove @:(%2)-,%0\n\tmove @:(%2)-%j2,%h0" );
}
else
{
RETURN_DSP ( "move (%2)+\n\tmove @:(%2)-,%0\n\tmove @:(%2)-%j2,%h0" );
}
}
}
else if ( REG == GET_CODE ( XEXP ( operands[1], 0 )))
{
operands[2] = XEXP ( operands[1], 0 );
if ( IS_SRC_OR_MPY_P ( REGNO ( operands[0] )))
{
RETURN_DSP ( "move (%2)+\n\tmove @:(%2)-,%g0\n\tmove @:(%2),%0" );
}
else
{
RETURN_DSP ( "move (%2)+\n\tmove @:(%2)-,%0\n\tmove @:(%2),%h0" );
}
}
else
{
if ( IS_SRC_OR_MPY_P ( REGNO ( operands[0] )))
{
return "move %f1+1,%g0\n\tmove %f1,%0";
}
else
{
return "move %f1+1,%0\n\tmove %f1,%h0";
}
}
}
case 4:
if ( is_float_p )
{
dtok ( NULL, *(union real_extract*)
&CONST_DOUBLE_LOW ( operands[1] ));
operands[2] =
gen_rtx ( CONST_INT, VOIDmode, adjusted_dval.i[1] );
operands[3] =
gen_rtx ( CONST_INT, VOIDmode, adjusted_dval.i[0] );
if ( IS_SRC_OR_MPY_P ( REGNO ( operands[0] )))
{
return "move #>%q2,%g0\n\tmove #>%q3,%0";
}
else
{
if ( 0 == INTVAL ( operands[3] ))
{
if ( 0 == INTVAL ( operands[2] ))
{
return "clr %0";
}
else
{
return "move #>%q2,%0";
}
}
else
{
return "move #>%q2,%0\n\tmove #>%q3,%h0";
}
}
}
else /* not a floating constant. */
{
if ( CONST_INT == GET_CODE ( operands[1] ))
{
if ( IS_SRC_OR_MPY_P ( REGNO ( operands[0] )))
{
if ( 0 == INTVAL ( operands[1] ))
{
return "move #0,%g0\n\tmove #%c1,%0";
}
else if ( 0 > INTVAL ( operands[1] ))
{
return "move #-1,%g0\n\tmove #>%q1,%0";
}
else
{
return "move #0,%g0\n\tmove #>%q1,%0";
}
}
else
{
if ( 0 == INTVAL ( operands[1] ))
{
return "clr %0";
}
else if ( 0 > INTVAL ( operands[1] ))
{
return "move #-1,%0\n\tmove #>%q1,%h0";
}
else
{
return "move #0,%0\n\tmove #>%q1,%h0";
}
}
}
operands[2] =
gen_rtx ( CONST_INT, VOIDmode,
(( CONST_DOUBLE_LOW ( operands[1] ) >> 24 ) & 0x0000ff ) |
(( CONST_DOUBLE_HIGH ( operands[1] ) << 8 ) & 0xffff00 ));
operands[3] =
gen_rtx ( CONST_INT, VOIDmode,
( CONST_DOUBLE_LOW ( operands[1] ) & 0xffffff ));
if ( IS_SRC_OR_MPY_P ( REGNO ( operands[0] )))
{
if ( rtx_equal_p ( operands[2], operands[3] ))
{
return "move #>%q2,%g0\n\tmove %g0,%0";
}
else
{
return "move #>%q2,%g0\n\tmove #>%q3,%0";
}
}
else
{
if ( 0 == INTVAL ( operands[3] ))
{
if ( 0 == INTVAL ( operands[2] ))
{
return "clr %0";
}
else
{
return "move #>%q2,%0";
}
}
else
{
if ( rtx_equal_p ( operands[2], operands[3] ))
{
return "move #>%q2,%0\n\tmove %0,%h0";
}
else
{
return "move #>%q2,%0\n\tmove #>%q3,%h0";
}
}
}
}
}
}
char*
move_pointer ( operands )
rtx *operands;
{
extern char mem_space;
if ( rtx_equal_p ( operands[0], operands[1] ))
{
return "";
}
switch ( which_alternative )
{
case 0:
if ( MEM_IN_STRUCT_P ( operands[0] ) ||
MEM_IN_STRUCT_P ( operands[1] ))
{
return "move %1,%0";
}
else
{
return "tfr %1,%0";
}
case 1:
return "move %e1,%0";
case 2:
if ( PLUS == GET_CODE ( XEXP ( operands[0], 0 )))
{
if ( REG == GET_CODE ( XEXP ( XEXP ( operands[0], 0 ), 0 )))
{
operands[2] = XEXP ( XEXP ( operands[0], 0 ), 0 );
operands[3] = XEXP ( XEXP ( operands[0], 0 ), 1 );
}
else
{
operands[2] = XEXP ( XEXP ( operands[0], 0 ), 1 );
operands[3] = XEXP ( XEXP ( operands[0], 0 ), 0 );
}
if ( CONST_INT != GET_CODE ( operands[3] ))
{
if ( load_n_reg_p ( operands[2], operands[3] ))
{
RETURN_DSP ( "move #%p3,%j2\n\tmove %e1,@:(%2+%j2)" );
}
else
{
RETURN_DSP ( "move %e1,@:(%2+%j2)" );
}
}
switch ( INTVAL ( operands[3] ))
{
case 0:
RETURN_DSP ( "move %e1,@:(%2)" );
case 1:
if ( REGNO ( operands[1] ) != REGNO ( operands[2] ))
{
RETURN_DSP ( "move (%2)+\n\tmove %e1,@:(%2)-" );
}
case -1:
if ( REGNO ( operands[1] ) != REGNO ( operands[2] ))
{
RETURN_DSP ( "move (%2)-\n\tmove %e1,@:(%2)+" );
}
default:
if ( load_n_reg_p ( operands[2], operands[3] ))
{
RETURN_DSP ( "move #%p3,%j2\n\tmove %e1,@:(%2+%j2)" );
}
else
{
RETURN_DSP ( "move %e1,@:(%2+%j2)" );
}
}
}
else
{
return "move %e1,%f0";
}
case 3:
if ( PLUS == GET_CODE ( XEXP ( operands[1], 0 )))
{
if ( REG == GET_CODE ( XEXP ( XEXP ( operands[1], 0 ), 0 )))
{
operands[2] = XEXP ( XEXP ( operands[1], 0 ), 0 );
operands[3] = XEXP ( XEXP ( operands[1], 0 ), 1 );
}
else
{
operands[2] = XEXP ( XEXP ( operands[1], 0 ), 1 );
operands[3] = XEXP ( XEXP ( operands[1], 0 ), 0 );
}
if ( CONST_INT != GET_CODE ( operands[3] ))
{
if ( load_n_reg_p ( operands[2], operands[3] ))
{
RETURN_DSP ( "move #%p3,%j2\n\tmove @:(%2+%j2),%0" );
}
else
{
RETURN_DSP ( "move @:(%2+%j2),%0" );
}
}
switch ( INTVAL ( operands[3] ))
{
case 0:
RETURN_DSP ( "move @:(%2),%0" );
case 1:
if ( REGNO ( operands[0] ) != REGNO ( operands[2] ))
{
RETURN_DSP ( "move (%2)+\n\tmove @:(%2)-,%0" );
}
case -1:
if ( REGNO ( operands[0] ) != REGNO ( operands[2] ))
{
RETURN_DSP ( "move (%2)-\n\tmove @:(%2)+,%0" );
}
default:
if ( load_n_reg_p ( operands[2], operands[3] ))
{
RETURN_DSP ( "move #%p3,%j2\n\tmove @:(%2+%j2),%0" );
}
else
{
RETURN_DSP ( "move @:(%2+%j2),%0" );
}
}
}
else
{
return "move %f1,%0";
}
case 4:
if ( 0 == INTVAL ( operands[1] ) ||
ADDR_REGS == REGNO_REG_CLASS ( REGNO ( operands[0] )))
{
if ( DST_REGS == REGNO_REG_CLASS ( REGNO ( operands[0] )))
{
return "clr %0";
}
else
{
return "move #%c1,%0";
}
}
else
{
return "move #>%c1,%0";
}
}
}
#if 0
int
local_constant_address_p ( x )
rtx x;
{
static int found_label_or_symbol_p ( );
switch ( GET_CODE ( x ))
{
case LABEL_REF:
case SYMBOL_REF:
return 1;
case CONST:
return found_label_or_symbol_p ( XEXP ( x, 0 ));
default:
return 0;
}
}
static int
found_label_or_symbol_p ( x )
rtx x;
{
if (( LABEL_REF == GET_CODE ( x )) || ( SYMBOL_REF == GET_CODE ( x )))
{
return 1;
}
else
{
char *p, *fmt = GET_RTX_FORMAT ( GET_CODE ( x ));
p = fmt;
while ( 'e' == *p )
{
if ( found_label_or_symbol_p ( XEXP ( x, p - fmt )))
{
return 1;
}
++ p;
}
}
return 0;
}
#endif
/* the following is a lot of bullshit to ensure that constants in the
assembly output *in no way* ever assume that the assembler will discard
the carry from arithmetic operations on constants. */
static rtx ensure_signed_pointer_offsets ( );
static rtx ensure_signed_int_offsets ( );
static int find_symbol ( );
rtx
ensure_pointer_result_size ( x )
rtx x;
{
int mask = (~((-1) << POINTER_SIZE ));
if ( CONST_INT == GET_CODE ( x ))
{
INTVAL ( x ) &= mask;
}
else if ( find_symbol ( x ))
{
x = ensure_signed_pointer_offsets ( x );
}
else
{
char *p, *fmt = GET_RTX_FORMAT ( GET_CODE ( x ));
p = fmt;
while ( '\0' != ( *p ))
{
if ( 'e' == ( *p ))
{
XEXP ( x, p - fmt ) =
ensure_pointer_result_size ( XEXP ( x, p - fmt ));
}
++ p;
}
}
return x;
}
rtx
ensure_integer_result_size ( x )
rtx x;
{
int mask = (~((-1) << BITS_PER_UNIT ));
if ( CONST_INT == GET_CODE ( x ))
{
INTVAL ( x ) &= mask;
}
else if ( find_symbol ( x ))
{
x = ensure_signed_int_offsets ( x );
}
else
{
char *p, *fmt = GET_RTX_FORMAT ( GET_CODE ( x ));
p = fmt;
while ( '\0' != ( *p ))
{
if ( 'e' == ( *p ))
{
XEXP ( x, p - fmt ) =
ensure_integer_result_size ( XEXP ( x, p - fmt ));
}
++ p;
}
}
return x;
}
static rtx
ensure_signed_pointer_offsets ( x )
rtx x;
{
if ( CONST_INT == GET_CODE ( x ))
{
INTVAL ( x ) = (( INTVAL ( x ) << ( HOST_BITS_PER_INT - POINTER_SIZE ))
>> ( HOST_BITS_PER_INT - POINTER_SIZE ));
}
else
{
char *p, *fmt = GET_RTX_FORMAT ( GET_CODE ( x ));
p = fmt;
while ( '\0' != ( *p ))
{
if ( 'e' == ( *p ))
{
XEXP ( x, p - fmt ) =
ensure_signed_pointer_offsets ( XEXP ( x, p - fmt ));
}
++ p;
}
}
return x;
}
static rtx
ensure_signed_int_offsets ( x )
rtx x;
{
if ( CONST_INT == GET_CODE ( x ))
{
INTVAL ( x ) =(( INTVAL ( x ) << ( HOST_BITS_PER_INT - BITS_PER_UNIT ))
>> ( HOST_BITS_PER_INT - BITS_PER_UNIT ));
}
else
{
char *p, *fmt = GET_RTX_FORMAT ( GET_CODE ( x ));
p = fmt;
while ( '\0' != ( *p ))
{
if ( 'e' == ( *p ))
{
XEXP ( x, p - fmt ) =
ensure_signed_int_offsets ( XEXP ( x, p - fmt ));
}
++ p;
}
}
return x;
}
static int
find_symbol ( x )
rtx x;
{
int found_symbol = 0;
char *p, *fmt = GET_RTX_FORMAT ( GET_CODE ( x ));
if ( SYMBOL_REF == GET_CODE ( x ))
{
return 1;
}
p = fmt;
while ( '\0' != ( *p ))
{
if ( 'e' == ( *p ))
{
found_symbol |= find_symbol ( XEXP ( x, p - fmt ));
}
++ p;
}
return found_symbol;
}
#include "config/dsp.c"